package org.ws.httphelper.support.pipeline.handler.response;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.ws.httphelper.common.Constant;
import org.ws.httphelper.core.pipeline.HandlerOrder;
import org.ws.httphelper.core.pipeline.ResponseHandler;
import org.ws.httphelper.exception.ResponseException;
import org.ws.httphelper.model.RequestContext;
import org.ws.httphelper.model.http.ResponseFuture;
import org.ws.httphelper.model.http.ResponseType;

import java.io.File;
import java.io.IOException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@HandlerOrder(1)
public class SaveFileHandler implements ResponseHandler {

    private static Logger log = LoggerFactory.getLogger(SaveFileHandler.class.getName());

    // 文件保存根路径
    private String rootPath = null;
    // 文件目录跟随URL一致
    private boolean followUrlPath = false;
    // 自定义从URL中抽取的正则表达式
    private String extractFileNameRegex = null;

    private Pattern extractFileNamePattern;

    private static final Pattern FILE_NAME_PATTERN = Pattern.compile(".*;\\s*filename\\=(.*)");

    public SaveFileHandler(String rootPath) {
        this.rootPath = rootPath;
    }

    public void setFollowUrlPath(boolean followUrlPath) {
        this.followUrlPath = followUrlPath;
    }

    public void setExtractFileNameRegex(String extractFileNameRegex) {
        this.extractFileNameRegex = extractFileNameRegex;
        this.extractFileNamePattern = Pattern.compile(extractFileNameRegex);
    }

    @Override
    public boolean handler(RequestContext requestContext) throws ResponseException {
        ResponseFuture responseFuture = requestContext.getResponseFuture();
        if (responseFuture.getResponseType() != ResponseType.BINARY) {
            return true;
        }
        if(responseFuture.isSuccess()){
            String url = responseFuture.getRequest().getUrl();
            String fileName = getFileName(responseFuture);
            String filePath = getFilePath(url);
            File out = new File(filePath+"/"+fileName);
            Object body = responseFuture.getResponse().getBody();
            try {
                // byte[]
                if(body instanceof byte[]){
                    FileUtils.writeByteArrayToFile(out,(byte[]) body);
                }
                // String
                else {
                    FileUtils.writeStringToFile(out,String.valueOf(body),responseFuture.getResponse().getCharset());
                }
                log.debug("save:{}",out.getPath());
            }
            catch (IOException e){
                throw new ResponseException(e.getMessage(),e);
            }
        }
        return true;
    }

    private String getFilePath(final String url){
        if(followUrlPath){
            String path = url;
            if(url.contains("?")) {
                path = url.substring(0, url.indexOf('?'));
            }
            int start = path.indexOf("/");
            if(start<0){
                start = 0;
            }
            int end = path.lastIndexOf("/");
            if(end<0){
                end = path.length();
            }
            return rootPath+"/"+path.substring(start,end)+"/";
        }
        else {
            return rootPath;
        }
    }

    /**
     * 获取文件名称
     * @param responseFuture
     * @return
     */
    private String getFileName(ResponseFuture responseFuture){
        String fileName = null;
        String url = responseFuture.getRequest().getUrl();
        // 优先使用URL自定义提取表达式
        if(StringUtils.isNotBlank(extractFileNameRegex)){
            Matcher matcher = this.extractFileNamePattern.matcher(url);
            if(matcher.find()){
                fileName = matcher.group(1);
            }
            log.debug("extractFileNameRegex:{}",fileName);
        }
        // 其次自动从多媒体文件中获取
        if(StringUtils.isBlank(fileName)) {
            String contentDisposition = responseFuture.getResponse().getHeaderValue(Constant.HEAD_CONTENT_DISPOSITION);
            if(StringUtils.isNotBlank(contentDisposition)) {
                Matcher matcher = FILE_NAME_PATTERN.matcher(contentDisposition);
                //
                if (matcher.find()) {
                    fileName = matcher.group(1);
                }
                if (StringUtils.isNotBlank(fileName) && fileName.contains("\"")) {
                    fileName = fileName.replaceAll("\"", "");
                }
            }
            log.debug("contentDisposition:{} -> {}",contentDisposition,fileName);
        }
        // 最后从url中获取
        if(StringUtils.isBlank(fileName)){
            int start = url.lastIndexOf("/");
            if(start<0){
                start = 0;
            }
            int end = url.lastIndexOf("?");
            if(end<0){
                end = url.length();
            }
            fileName = url.substring(start,end);

            log.debug("url -> {}",fileName);
        }
        String contentType = responseFuture.getResponse().getHeaderValue(Constant.HEAD_CONTENT_TYPE);
        String type = ".jpg";
        if(StringUtils.isNotBlank(contentType)) {
            contentType = contentType.toLowerCase();
            if (contentType.contains("jpeg")) {
                type = ".jpg";
            } else if (contentType.contains("png")) {
                type = ".png";
            }
        }
        if(fileName.endsWith(type)) {
            return fileName;
        }
        else {
            return fileName + type;
        }
    }

}
